package cn.lyjuan.first.netty.demo._5_netty_heartbeat.server;

import cn.lyjuan.first.netty._4_netty_serialize.msg.codec.MessageCodec;
import cn.lyjuan.first.netty._4_netty_serialize.msg.reader.ReaderFactory;
import cn.lyjuan.first.netty._4_netty_serialize.msg.reader.impl.HelloReaderImpl;
import cn.lyjuan.first.netty._4_netty_serialize.msg.reader.impl.MsgReaderImpl;
import cn.lyjuan.first.netty.demo._5_netty_heartbeat.cst.HeartbeatConst;
import cn.lyjuan.first.netty.demo._5_netty_heartbeat.msg.reader.impl.HeartReaderImpl;
import cn.lyjuan.first.netty.demo._5_netty_heartbeat.server.handler.ServerHandler;
import cn.lyjuan.first.netty.demo._5_netty_heartbeat.server.handler.ServerHeartHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.concurrent.TimeUnit;

public class Server
{
    private static Logger log = LogManager.getLogger(Server.class);

    public static final int PORT = 8888;

    public static void main(String[] args) throws InterruptedException
    {
        ServerBootstrap strap = new ServerBootstrap();

        NioEventLoopGroup boss = new NioEventLoopGroup();
        NioEventLoopGroup worker = new NioEventLoopGroup();

        try
        {
            Channel chl = start(strap, boss, worker);

            chl.closeFuture().sync();// 等待关闭
        } finally
        {
            if (!boss.isShutdown())
                boss.shutdownGracefully();
            if (!worker.isShutdown())
                worker.shutdownGracefully();
        }

    }

    private static Channel start(ServerBootstrap strap, NioEventLoopGroup boss, NioEventLoopGroup worker) throws InterruptedException
    {
        ReaderFactory readerFactory = new ReaderFactory();
        readerFactory.addReader(new HelloReaderImpl());
        readerFactory.addReader(new MsgReaderImpl());
        readerFactory.addReader(new HeartReaderImpl());

        strap.group(boss, worker)
                .localAddress(PORT)
                .channel(NioServerSocketChannel.class)
                .handler(new LoggingHandler(LogLevel.INFO))
                .childHandler(new ChannelInitializer<SocketChannel>()
                {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception
                    {
                        ch.pipeline().addLast(new IdleStateHandler(HeartbeatConst.IDLE_TIMEOUT, 0, 0, TimeUnit.SECONDS));
                        ch.pipeline().addLast(new MessageCodec().setReaderFactory(readerFactory));
                        ch.pipeline().addLast(new ServerHandler());
                        ch.pipeline().addLast(new ServerHeartHandler());
                    }
                })
        .option(ChannelOption.SO_BACKLOG, 10)
        .childOption(ChannelOption.SO_KEEPALIVE, true);

        ChannelFuture future = strap.bind().sync();

        log.info("server start on " + PORT);

        return future.channel();
    }
}
